package com.sikaryofficial.backend.utils;

import com.sikaryofficial.backend.domain.vo.ImportArticleContentVO;
import com.sikaryofficial.common.core.domain.R;
import com.sikaryofficial.common.core.utils.SpringUtils;
import com.sikaryofficial.common.core.utils.file.FileUtils;
import com.sikaryofficial.system.api.RemoteFileService;
import com.sikaryofficial.system.api.domain.SysFile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPicture;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;

import static com.sikaryofficial.common.core.utils.file.FileUtils.fileToMultipartFile;

/**
 * word 文件- easyPOI 工具读取
 * <p>
 * <p>
 * 如果是word模版导出，可以选用下面的框架
 * poi-tl是一个免费开源的Java类库，是基于Apache POI的模板引擎，
 * 纯Java组件，跨平台，代码短小精悍，通过插件机制使其具有高度扩展性。
 */
@Slf4j
public class WordProcessUtil {

    private static final String tmpPath = "/data/tmp/wordAnalysis/";

    public static void main(String[] args) throws Exception {
        testReadWord();
    }

    /**
     * word文档解析 (仅支持docx格式)
     *
     * @param multipartFile
     * @return
     * @throws IOException
     */
    public static List<ImportArticleContentVO> wordAnalysis(MultipartFile multipartFile) throws IOException {
        byte[] byteArr = multipartFile.getBytes();
        List<ImportArticleContentVO> contentList = Lists.newArrayList();
        try (InputStream inputStream = new ByteArrayInputStream(byteArr);
             XWPFDocument document = new XWPFDocument(inputStream)) {
            /** 1. 图片与所在段落的关系： 图片在Word文档中通常是作为XWPFRun对象的一部分嵌入在XWPFParagraph中。可以通过遍历段落中的XWPFRun来查找包含图片的运行：*/
            for (IBodyElement bodyElement : document.getBodyElements()) {
                processWord(contentList, bodyElement);
            }
        } catch (Exception e) {
            log.error("wordAnalysis error {}", e);
        } finally {
            FileUtils.deleteFile(tmpPath);
        }
        return contentList;
    }

    private static void processWord(List<ImportArticleContentVO> contentList, IBodyElement bodyElement) throws IOException {
        if (bodyElement instanceof XWPFParagraph) {
            XWPFParagraph paragraph = (XWPFParagraph) bodyElement;
            // 文本处理
            processTxt(contentList, paragraph);
            for (XWPFRun run : paragraph.getRuns()) {
                if (run.getEmbeddedPictures() != null && !run.getEmbeddedPictures().isEmpty()) {
                    for (XWPFPicture pic : run.getEmbeddedPictures()) {
                        // 图片处理
                        processPic(contentList, pic);
                    }
                }
            }
        }
    }

    private static void processTxt(List<ImportArticleContentVO> contentList, XWPFParagraph bodyElement) {
        ImportArticleContentVO content = ImportArticleContentVO.builder()
                .type(0)
                .content(bodyElement.getText())
                .build();
        contentList.add(content);
    }

    private static void processPic(List<ImportArticleContentVO> contentList, XWPFPicture pic) throws IOException {
        XWPFPictureData picData = pic.getPictureData();
        File dir = new File(tmpPath);
        dir.mkdirs();
        String tmpFile = tmpPath + picData.getFileName();
        File genLocalZipFile = FileUtils.convertByteArrayToFile(picData.getData(), tmpFile);
        // 上传文件
        RemoteFileService remoteFileService = SpringUtils.getBean(RemoteFileService.class);
        R<SysFile> sysFileR = remoteFileService.upload(fileToMultipartFile(genLocalZipFile));
        String downloadTaskFileUrl = "";
        if (Objects.nonNull(sysFileR) && Objects.nonNull(sysFileR.getData())) {
            downloadTaskFileUrl = sysFileR.getData().getUrl();
        }
        ImportArticleContentVO content = ImportArticleContentVO.builder()
                .type(1)
                .content(downloadTaskFileUrl)
                .build();
        contentList.add(content);
    }

    public static void testReadWord() throws IOException {
        String basePath = "E:\\word_test_file\\";
        FileInputStream fis = new FileInputStream(basePath.concat("myTestFile.docx"));
        XWPFDocument document = new XWPFDocument(fis);
        // 读取文档中的所有段落文本
        List<IBodyElement> bodyElements = document.getBodyElements();
        for (IBodyElement bodyElement : document.getBodyElements()) {
            if (bodyElement instanceof XWPFParagraph) {
                XWPFParagraph paragraph = (XWPFParagraph) bodyElement;
            }
        }
        /** 1. 图片与所在段落的关系： 图片在Word文档中通常是作为XWPFRun对象的一部分嵌入在XWPFParagraph中。可以通过遍历段落中的XWPFRun来查找包含图片的运行：*/
        List<ImportArticleContentVO> contentList = Lists.newArrayList();
        for (IBodyElement bodyElement : document.getBodyElements()) {
            if (bodyElement instanceof XWPFParagraph) {
                XWPFParagraph paragraph = (XWPFParagraph) bodyElement;
                ImportArticleContentVO content = ImportArticleContentVO.builder()
                        .type(0)
                        .content(paragraph.getText())
                        .build();
                contentList.add(content);
                for (XWPFRun run : paragraph.getRuns()) {
                    if (run.getEmbeddedPictures() != null && !run.getEmbeddedPictures().isEmpty()) {
                        for (XWPFPicture pic : run.getEmbeddedPictures()) {
                            XWPFPictureData picData = pic.getPictureData();
                            picData.getData();
                            ImportArticleContentVO content1 = ImportArticleContentVO.builder()
                                    .type(1)
                                    .content("xxxxxxx")
                                    .build();
                            contentList.add(content1);
                        }
                    }
                }
            }
        }
        /**2. 图片在表格单元格中的位置： 如果图片位于表格单元格中，需要遍历表格(XWPFTable)及其单元格(XWPFTableCell)，并在每个单元格内部重复上述查找图片在XWPFRun中的过程： */
//        for (IBodyElement bodyElement : document.getBodyElements()) {
//            if (bodyElement instanceof XWPFTable) {
//                XWPFTable table = (XWPFTable) bodyElement;
//                for (XWPFTableRow row : table.getRows()) {
//                    for (XWPFTableCell cell : row.getTableCells()) {
//                        // 在这里对cell内的内容进行类似上述的处理，查找图片
//                    }
//                }
//            }
//        }
        // 读取文档中的所有图片
        for (XWPFPictureData pictureData : document.getAllPictures()) {
            byte[] data = pictureData.getData();
            String filename = pictureData.getFileName();
            // 将图片保存到本地文件系统
            File outputPictureFile = new File(basePath.concat(filename));
            try (FileOutputStream fos = new FileOutputStream(outputPictureFile)) {
                fos.write(data);
            }
        }
        document.close();
        fis.close();
    }
}
